 ///
 /// @file    virtualFunction.cc
 /// @author  lemon(haohb13@gmail.com)
 /// @date    2023-05-03 16:20:27
 ///
 
#include <iostream>
using std::cout;
using std::endl;

class Base
{
public:
	//构造函数不能设置为虚函数, 为什么?
	//virtual 
	Base(long base)
	: _base(base)
	{	cout << "Base(long)" << endl;	}

	virtual
	void print() const
	{	cout << "Base::_base : " << _base << endl;	}

	//使用虚函数时，必须要用到对象的指针
	//静态成员函数没有this指针，所以不能设置为虚函数
	/* virtual */
	/* static void display() */ 
	/* {} */

	//当inline和virtual同时出现时，inline关键字失效
	//inline
	virtual 
	void show() const 
	{	cout << "Base::show()" << endl;	}

	void func() 
	{
		//在类内部实现的函数，统统都是inline函数
	}

private:
	long _base;
};

class Derived
: public Base
{
public:
	Derived(long base, long derived)
	: Base(base)
	, _derived(derived)
	{	cout << "Derived(long,long)" << endl;	}

private:
	//派生类重定义虚函数, 发生了覆盖(override)
	//其形式必须要与基类同名函数完全一致
	void print() const override 
	{	cout << "Derived::_derived: " << _derived << endl;}

	virtual
	void print(int) const//这是新的虚函数
	{	cout << "print(int)" << endl;	}

private:
	long _derived;
};

//虚函数是怎么实现的？
//答: 当类中定义了一个虚函数时，在对象的存储布局的
//开始位置会多一个虚函数指针，该虚函数指针指向了
//一个虚函数表，简称虚表，虚表中存放的是虚函数的
//入口地址


//动态多态被激活的条件是什么？
//答:1. 基类定义虚函数
//	 2. 派生类要重定义虚函数
//	 3. 要创建派生类对象
//	 4. 基类指针指向派生类对象
//	 5. 基类指针调用虚函数
//最终的效果是同基类指针可以调用到派生类的虚函数

//使用虚函数有什么优势？
//答: 当希望取扩展功能时，用同一种接口进行调用，
//但最终调用的新的功能的实现时，就可以采用虚函数了
//方便代码的扩展, 不需要改变原有的代码

class Derived2
: public Base
{
public:
	Derived2(long base, long derived)
	: Base(base)
	, _derived2(derived)
	{	cout << "Derived(long,long)" << endl;	}

	void print() const 
	{	cout << "Derived::_derived2: " << _derived2 << endl;}

private:
	long _derived2;
};

void display(Base * pbase)
{	//如果在编译期，只会调用基类的print方法
	pbase->print();//同一条指令，不同的对象执行不同的行为
}
 
void test0() 
{
	cout << "sizeof(Base):" << sizeof(Base) << endl;
	cout << "sizeof(Derived):" << sizeof(Derived) << endl;
	Base base(100);
	Derived derived(1, 10);
	Derived2 derived2(2, 20);

	display(&base);
	display(&derived);
	display(&derived2);
} 
 
int main(void)
{
	test0();
	return 0;
}
